<script setup lang="ts">
import {computeHash} from '../../../utils/Md5Utils.ts'
import { UploadFilled } from '@element-plus/icons-vue'
import {ref} from "vue";


import { uploadFileChuunkApi,Result, mergerFileFileApi, findChunkListApi} from '../FileApi.ts'
import type { UploadInstance } from 'element-plus'
import {digElMessage} from "../../../common/Message.ts";
const uploadRef = ref<UploadInstance>()

let fileMd5=ref(""); //文件md5

let fileName=ref("");//文件原始名称

let file=ref<File>(); //保存要上传的文件

let fileSuffix=ref("");//文件后缀


let chunkSize:number=5*1024*1024;//每一个分片文件大小


let chunkCount=0;//需要上传的分片文件数量

let uploadChunCount=ref(0);//已经上传的分片文件数量


let ChunkNum=0;//分片出来的文件数量

let achunNum=0;//已经上传到服务器的文件数量


//计算文件上传进度
const countPercent=()=>{

  percentage.value=(((achunNum+uploadChunCount.value))/ChunkNum*80)
}
let controler=ref(true)
interface requestType{
    file:Blob,
    fileMd5:string,
    sortIndex:number

}

let requestPool:Array<requestType>=[]// 请求池，存储待上传的切片信息

let MAX_REQUEST=6;//最大并发请求数量


let uploadFIle=ref<Array<number>>([]);

//获取文件md5
const computeHashData=async (e:File)=>{

  ChunkNum=e.size/chunkSize;
  file.value=e;
  fileName.value=e.name;
  fileSuffix.value=e.name.substring(e.name.lastIndexOf(".")+1)
  show.value=true
  await computeHash(e).then(res=>{
     fileMd5.value=res;


  })


}

//切割文件数组
/**文件切片并且放入请求池中 */
const fileSlice = (file: File, chunkSize: number):Promise<Array<requestType>> => {
   return  new Promise((resolve)=>{
     let pool:Array<requestType>=[]
     let index = 0
     for (let nowSize = 0; nowSize < file.size; nowSize += chunkSize) {

   if(!uploadFIle.value!.includes(index)){
     pool.push({ file:file.slice(nowSize, nowSize + chunkSize),fileMd5:fileMd5.value, sortIndex: index})
     requestPool.push({ file:file.slice(nowSize, nowSize + chunkSize),fileMd5:fileMd5.value, sortIndex: index})
     chunkCount++;
   }
       index++
     }
     ChunkNum=index;
     resolve(pool)
   })


}


//处理请求池中的数据

const  processPool=async ()=>{
  //控制并发
  while (requestPool.length > 0 && MAX_REQUEST> 0&&controler.value){
    let chunkData=requestPool.shift(); // 取出一个待上传的切片
     //上传切片
   await uploadChunk(chunkData!).then(async res=>{
        //更新上传进度
     uploadChunCount.value++;

     countPercent()





      if(requestPool.length>0){
         await processPool();
      }





      if(chunkCount==uploadChunCount.value){

        if(controler.value){  controler.value=false; await merger();}



        return;
      }

    }).finally(
       ()=>{
         //@ts-ignore
         MAX_REQUEST++
       }
   )
  MAX_REQUEST--
}}

//上传单个切切片

function uploadChunk(data:requestType):Promise<Result<any>>{

  let formData = new FormData();
    formData.append("file", data.file);
    formData.append("fileMd5", data.fileMd5);
    //@ts-ignore
    formData.append("fileIndex", data.sortIndex);
  return  uploadFileChuunkApi(formData)

}
const beforeUpload=async (e:File)=>{
  //计算hash
  await  computeHashData(e);

  await  getUploadChunkIndex();
    //切割文件
 await fileSlice(e,chunkSize);

 if(requestPool.length==0){
  await merger();
   return  false;
 }
 else{
   return true;
 }

  //uploadRef.value!.submit()
   //上传切片数组

}



const  getUploadChunkIndex=async ()=>{

  let form=new FormData();
  form.append("fileMd5",fileMd5.value)
 await findChunkListApi(form).then(res=>{
   uploadFIle.value=res.data;
   achunNum=res.data.length
   countPercent();


  })
}



// const suspend=()=>{
//   console.log("取消上传")
//   axiosCancel();
//   controler.value=false
// }
// const retryFile=async ()=>{
//   controler.value=true;
//   await processPool();
// }

let percentage=ref(0);


const format = (percentage:number) => (percentage === 0 ? '计算MD5' : `${percentage}%`)


let show=ref(false);

//合并分片
const merger=async ()=>{



 let time=setInterval(()=>{  percentage.value+=1;},1000)

 await mergerFileFileApi({
      fileMd5:fileMd5.value,
    fileName:fileName.value,
    fileSuffix:fileSuffix.value
  }).then(res=>{
   clearInterval(time)
   show.value=false;
     controler.value=false

     digElMessage("上传成功","success",1000)

  }).catch(()=>{

   clearInterval(time)

 })
}
</script>

<template>

  <el-upload
      class="upload-demo"
      drag
      ref="uploadRef"
      :auto-upload="true"
      :before-upload="beforeUpload"
      :http-request="processPool"
      multiple
  >

    <el-icon class="el-icon--upload"><upload-filled /></el-icon>
    <div class="el-upload__text">
      Drop file here or <em>click to upload</em>
    </div>
    <template #tip>

    </template>

<!--    -->



  </el-upload>
<!--  <div class="el-upload__tip">-->

<!--    <el-button size="small" type="primary" @click="suspend" slot='tip'>取消上传</el-button>-->

<!--    <el-button size="small" type="primary" @click="retryFile" slot='tip'>上传</el-button>-->
<!--  </div>-->





 <div v-if="show">
   <el-progress :percentage="percentage" :format="format"   duration="8" />

 </div>
</template>

<style scoped lang="less">


</style>